package com.mygame.common.utils;

import org.apache.commons.configuration2.CompositeConfiguration;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Author: shushenglin
 * Date:   2017/2/23 16:39
 */
public class PropertyReader {
	private static final Logger logger = LoggerFactory.getLogger(PropertyReader.class);
	public static final String PROPERTIES_EXT = "properties";

	private static Configuration config = new CompositeConfiguration();
	private static final Configurations configurations = new Configurations();

	private static class PropertyFile{
		private File file;
		private long lastModified = 0;

		PropertyFile(File file) {
			this.file = file;
		}

		PropertyFile(String fileName) {
			this(new File(fileName));
		}

		File getFile() {
			return file;
		}

		void update() {
			this.lastModified = file.lastModified();
		}

		boolean isModified(){
			return this.lastModified == 0 ||  this.lastModified < file.lastModified();
		}

	}
	private static List<PropertyFile> properties = new ArrayList<>();

	public static void addFolder(String folder){
		addFolder(folder, PROPERTIES_EXT, true);
	}

	public static int addFolder(String folder, String ext, boolean recursive){
		if (StringUtils.isBlank(ext)){
			ext = PROPERTIES_EXT;
		}
		File dir = new File(folder);
		if (!dir.exists() ||  !dir.isDirectory()){
			 return 0 ;
		}
		Collection<File> props = FileUtils.listFiles(dir, new String[]{ext}, recursive);
		for (File f : props) {
			addFile(f);
		}
		return props.size();
	}

	public static void addFile(String file) {
		properties.add(new PropertyFile(file));
	}

	public static void addFile(File f) {
		properties.add(new PropertyFile(f));
	}

	public static void refresh(){
		boolean modified = false;
		for (PropertyFile f : properties){
			if (f.isModified()){
				modified = true;
				break;
			}
		}
		if (modified){
			init();
		}
	}

	public static void init(){
		try {
			CompositeConfiguration conf = new CompositeConfiguration();
			for (PropertyFile f : properties){
				logger.info("load properties {}", f.getFile().getName());
				conf.addConfiguration(configurations.properties(f.getFile()));
				f.update();
			}
			config = conf;
		} catch (ConfigurationException e) {
			logger.error("read property file fail", e);
		}
	}

	public static boolean containsKey(String key) {
		return config.containsKey(key);
	}

	public static boolean getBoolean(String key) {
		return config.getBoolean(key);
	}

	public static boolean getBoolean(String key, boolean defaultValue) {
		return config.getBoolean(key, defaultValue);
	}

	public static double getDouble(String key) {
		return config.getDouble(key);
	}

	public static double getDouble(String key, double defaultValue) {
		return config.getDouble(key, defaultValue);
	}

	public static float getFloat(String key) {
		return config.getFloat(key);
	}

	public static float getFloat(String key, float defaultValue) {
		return config.getFloat(key, defaultValue);
	}

	public static int getInt(String key) {
		return config.getInt(key);
	}

	public static int getInt(String key, int defaultValue) {
		return config.getInt(key, defaultValue);
	}

	public static long getLong(String key) {
		return config.getLong(key);
	}

	public static long getLong(String key, long defaultValue) {
		return config.getLong(key, defaultValue);
	}

	public static String getString(String key) {
		return config.getString(key);
	}

	public static String getString(String key, String defaultValue) {
		return config.getString(key, defaultValue);
	}
}
